Ask The Oracle [crypto]

Ask The Oracle

Mr Robot has worked all night to find the Cipher "TIe8CkeWpqPFBmFcIqZG0JoGqBIWZ9dHbDqqfdx2hPlqHvwH/+tbAXDSyzyrn1Wf" then he faints of Overdose.You are left with a challenge to get the key to the database before EVIL CORP starts backing up the data.

  • URL: ctf.pragyan.org 8500

Recon

The server asks for a ciphertext and IV. After that the server just spits out the actual IV used for the given ciphertext. The server will tell you if the padding is wrong of the decrypted ciphertext that we can provide. It is therefore vulnerable to a padding oracle attack.

Code

import pwn
from base64 import b64encode, b64decode
pwn.context.log_level = pwn.logging.ERROR

cipher = "TIe8CkeWpqPFBmFcIqZG0JoGqBIWZ9dHbDqqfdx2hPlqHvwH/+tbAXDSyzyrn1Wf"
cipherb = b64decode(cipher)
iv = "VGhpcyBpcyBhbiBJVjQ1Ng=="
ivb = b64decode(iv)
allb = ivb + cipherb

def send(cipher, iv):
    conn = pwn.remote('ctf.pragyan.org', 8500)
    conn.recvuntil('Enter in format \'<Ciphertext>|<Initialisation Vector>\'\n')
    conn.send(f'{cipher}|{iv}\n'.encode())
    conn.recvuntil('VGhpcyBpcyBhbiBJVjQ1Ng==\n')
    res = conn.recv()
    conn.close()
    return b'Cipher Error!\n' in res

plain = []
for block in range(len(allb), 16, -16):
    pad = []
    c2 = b64encode(bytearray(allb[block - 16:block])).decode()

    for byte in range(1, 17):
        c1b = allb[block - 16 - byte]
        c1 = (16 - byte) * [0xf0] + [0] + [p ^ byte for p in pad]

        for i in range(0, 256):
            if c1b ^ (i ^ byte) > 126:
                continue
            c1[-byte] = i

            if send(c2, b64encode(bytes(c1)).decode()):
                pad.insert(0, i ^ byte)
                plain.insert(0, c1b ^ (i ^ byte))
                break
        print(plain)

print(''.join([chr(p) for p in plain]))

Flag

pctf{b@d_p@nd@s_@r3_3v3rywh3r3_c@tch}